<template>
	<Row class="form-field"
	     :class="{'form-field-no-validate':!validate,'form-field-view':view}">
		<div class="dev-inner-box"
		     v-if="dev">
			<Button type="primary"
			        icon="android-map"
			        shape="circle"
			        size="small"></Button>
		</div>
		<div class="fieldset-wrapper"
		     v-for="(fieldset,fieldsetIndex) in formFieldset"
		     v-if="fieldset.fields.length"
		     :key="fieldset.code">
			<div v-if="fieldset.name"
			     class="fieldset-header"
			     @click="fieldsetCollaspe(fieldset)">
				<h4 v-html="fieldset.name"></h4>
				<div class="collapse-box">
					<Icon v-if="fieldset.collapse"
					      type="chevron-down"></Icon>
					<Icon v-else
					      type="chevron-up"></Icon>
				</div>
			</div>
			<div class="fieldset-body"
			     :class="{'fieldset-body-collapse':fieldset.collapse}">
				<div v-for="(field,index) in fieldset.fields"
				     class="field-group ivu-col"
				     v-show="fieldStatus[field.code].show!==false"
				     :class="groupClass(field)"
				     :key="field.code">
					<Col class="field-label"
					     :data-code="field.code"
					     :span="fieldLabelCol(field)">
					<label :class="{reuqire:field.required&&field.editable!==false}">
						{{field.name}}
					</label>
					</Col>
					<Col class="field-input"
					     :class="{'field-has-tip':hasTextTip}"
					     :span="fieldControlCol(field)">
					<component v-if="!view || !field.tpl || !enableTpl"
					           @enter="inputEnter"
					           class="field-control"
					           :ref="'field_'+field.code"
					           :forceEnable="forceEnable(field)"
					           :parentData="parentData"
					           @validate="fieldValidate(field,$event)"
					           :hasValidate="fieldStatus[field.code].show===false?false:validate"
					           :validator="formValidte"
					           :model="field"
					           :require="field.required"
					           @change="dataChange"
					           :rowData="formData"
					           :is="fieldControl(field)"
					           :size="controlSize"
					           :value="formData[field.code]"
					           @input="fieldInput(field,$event)"
					           @extInput="extFieldInput($event)"
					           :status="fieldStatus[field.code]"></component>
					<div class="field-control field-text"
					     v-else
					     v-html="renderData(field)"></div>
					<div class="field-tip"
					     v-if="hasTextTip && tipState"
					     v-html="tipText(field)"></div>
					</Col>
				</div>
				<div class="clear"></div>
			</div>
			<hr v-if="fieldsetIndex<formFieldset.length-1" />
		</div>
		<template v-if="hasSlaves && formModel.slaves && formModel.slaves[0]">
			<div class="field-group slave-group ivu-col"
			     v-if="formModel.layout!=='tab'"
			     v-for="(slave,index) in formModel.slaves"
			     :class="slaveGroupClass(slave)"
			     :key="slave.code">
				<Col class="field-label"
				     :span="slaveLabelCol(slave)">
				<label>
					{{ slave.name}}
				</label>
				</Col>
				<Col class="field-input"
				     :span="slaveControlCol(slave)">
				<component @enter="inputEnter"
				           :viewMode="view"
				           :is="slaveComponent(slave)"
				           :defaultData="slaveDefaultData[slave.code]"
				           @updateData="updateSlave(slave.fieldCode,$event)"
				           :ref="slave.code"
				           :data="formData[slave.code]"
				           :module="slave.code"
				           :model="slave"
				           :hasCheck="listSingleSelect?false:true"
				           :singleSelect="listSingleSelect"
				           :actionModalTransfer="actionModalTransfer"
				           @fieldTrigger="slavefieldTrigger(slave.code,$event)"></component>
				</Col>
			</div>
			<div class="field-group field-group-tabs  ivu-col"
			     v-if="formModel.layout==='tab'"
			     :key="tabsKey">
				<Tabs class="ivu-col ivu-col-span-24"
				      :animated="false"
				      :type="listLeftTab?'card':'line'"
				      :value="formModel.slaves[0] && formModel.slaves[0].code"
				      :class="{'tab-left':listLeftTab}"
				      v-model="slavesTab">
					<TabPane :label="slave.name"
					         :name="slave.code"
					         v-for="(slave,index) in formSlaves"
					         :key="slave.code"
					         :data-code="slave.code">
						<component @enter="inputEnter"
						           :viewMode="view"
						           :is="slaveComponent(slave)"
						           :defaultData="slaveDefaultData[slave.code]"
						           @updateData="updateSlave(slave.fieldCode,$event)"
						           :ref="slave.code"
						           :actionModalTransfer="actionModalTransfer"
						           :data="formData[slave.code]"
						           :module="slave.code"
						           :model="slave"
						           :hasCheck="listSingleSelect?false:true"
						           :singleSelect="listSingleSelect"
						           :mainForm="thisForm"
						           @fieldTrigger="slavefieldTrigger(slave.code,$event)"></component>
					</TabPane>
				</Tabs>
			</div>
		</template>
	</Row>
</template>

<script>
import Fields from 'field';
import FieldsType from 'field/type';
import moduleStore from 'store/type/form';
import tableList from '@/components/localGridPanel/index';
import attachmentList from '@/components/attachmentList/index';
import TabsPro from '@/element/tabsPro';
import tableEditor from '@/components/gridTableEditor/index';
import Formula from '@/common/formula';
import Render from '@/common/render';
import $ from '@/common';
//自动分行宽度
const colList = [400, 900, 1100, 1400, 1600];
export default {
	moduleStore,
	props: {
		data: {
			default() {
				return {};
			},
		},
		model: {},
		value: {},
		isBuild: {},
		controlSize: {},
		col: {
			type: Number,
		},
		searchMode: {
			default: false,
		},
		//label占行，可根据长度进行调整
		labelCol: {
			type: Number,
			default: 4,
		},
		validate: {
			default: true,
		},
		hasFullRow: {
			default: true,
		},
		hasSlaves: {
			default: true,
		},
		//强制可编辑
		allEnable: {
			default: null,
		},
		//根据form大小调整数据行数
		autoCol: {
			default: null,
		},
		initData: {
			default: null,
		},
		//注入数据，首次加载应用
		impData: {
			default: null,
		},
		enableColCount: {
			default: true,
		},
		isXList: {
			default: false,
		},
		view: {},
		listSingleSelect: {
			default: false,
		},
		listLeftTab: {
			default: false,
		},
		actionModalTransfer: {},
	},
	watch: {
		data(v) {
			this.setData(v);
		},
		value(v) {
			this.setData(v);
		},
		model(v) {
			this.setModel($.copy(v));
		},
		initData() {
			this.initDefaultData();
		},
		formData(v) {
			if (this.formModel.fields && !this.formModel.fields.length) {
				this.eventUpdate();
			}
		},
		slavesTab(v) {
			var slave = this.$refs[v] && this.$refs[v][0];
			if (slave && slave.redraw) {
				slave.redraw();
			}
		},
		slaveShow() {
			this.tabsKey = false;
			this.$nextTick = () => {
				this.tabsKey = true;
			};
		},
	},
	data() {
		return {
			//允许在view状态下使用tpl渲染，临时开关
			enableTpl: true,
			isForm: true,
			formValidte: false,
			fieldStatus: {},
			validateSet: new Set(),
			isValidate: true,
			slaveDefaultData: {},
			parentData: {},
			formEvent: {},
			fieldEvent: {},
			fieldsetList: {},
			slaveShow: {},
			slavesTab: null,
			tabsKey: true,
			tipState: true,
      tipContent : {}
		};
	},
	computed: {
		formSlaves() {
			return this.formModel.slaves.filter(slave => {
				return slave && this.slaveShow[slave.code] !== false;
			});
		},
		thisForm() {
			return this;
		},
		dev() {
			return $.dev;
		},
		formFields() {
			return this.moduleState.formModel.fields
				.filter(v => {
					return v.cardpos !== 0 && v.type !== 'pk';
				})
				.sort((a, b) => {
					return a.cardpos - b.cardpos;
				});
		},
		hasTextTip() {
			for (let field of this.formFields) {
				if (field.tip && field.tip !== '提示信息') return true;
			}
			return false;
		},
		formFieldset() {
			var data = [];
			var list = this.fieldsetList;

			for (let i in this.fieldsetList) {
				this.fieldsetList[i].fields = [];
			}

			for (let i in this.formFields) {
				var field = this.formFields[i];
				if (list[field.fieldset]) {
					list[field.fieldset].fields.push(field);
				} else {
					list.default.fields.push(field);
				}
			}
			for (let i in list) {
				if (list[i].fields.length) {
					data.push(list[i]);
				}
			}
			return data.sort((a, b) => {
				return a.index - b.index;
			});
		},
		formCol() {
			//根据表单宽度进行分行，由于首次计算数据计算时当前组件元素并未挂载，因此使用父级组件的宽度进行计算，需注意设置
			var col = (this.enableColCount && this.formModel.col_count) || this.col;
			if (col) return col;
			if (this.autoCol !== null) {
				let width = this.$parent.$el.offsetWidth;
				for (let i = 0; i < colList.length; i++) {
					if (width <= colList[i] || i === colList.length - 1) {
						col = i + 1 + this.autoCol;
						if (col <= 0) col = 1;
						break;
					}
				}
			}
			if (this.hasTextTip) {
				col = col - 1;
			}
			return col || 1;
		},
	},
	methods: {
    getTip () {
      return this.tipContent
    },
		updateTip() {
			this.tipState = false;
			this.$nextTick(() => {
				this.tipState = true;
			})
		},
		redraw() {
			if (this.formModel.slaves) {
				this.formModel.slaves.forEach(slave => {
					if (this.$refs[slave.code] && this.$refs[slave.code][0]) {
						this.$refs[slave.code][0].redraw();
					}
				});
			}
		},
		renderData(field) {
			if (this.view && field.tpl) {
				return Render.tpl($.composeValue(field.tpl, this.formData), field, this.formData);
			} else {
				return this.formData[field.code];
			}
		},
		//字段组件触发自定义事件
		fieldTrigger(field, e) {
			this.$emit('fieldTrigger', {
				field,
				code: field.code,
				data: e,
			});
		},
		slavefieldTrigger(code, e) {
			this.$emit('slavefieldTrigger', {
				slave: code,
				...e,
			});
		},
		inputEnter() {
			this.$emit('form-enter');
		},
		//初始化默认数据
		initDefaultData() {
			this.setData(this.initData);
			var slaveDefaultData = {};
			for (let i in this.initData) {
				if (i.indexOf('.') > 0) {
					let arr = i.split('.');
					var code = arr.shift();
					if (!slaveDefaultData[code]) {
						slaveDefaultData[code] = {};
					}
					slaveDefaultData[code][arr.join('.')] = this.initData[i];
				}
			}
			this.$set(this, 'slaveDefaultData', slaveDefaultData);
		},
		forceEnable(field) {
			if (this.view === true) {
				return false;
			} else if (this.allEnable) {
				return this.allEnable;
			} else {
				if (this.fieldStatus[field.code] && this.fieldStatus[field.code].enable !== null) {
					return this.fieldStatus[field.code].enable;
				}
			}
			return null;
		},
		getData() {
			var data = {
				...this.formData,
			};
			//清除status:0的数据
			for (let i in this.formModel.fields) {
				var field = this.formModel.fields[i];
				if (field.status === 0 && data[field.code] !== undefined) {
					delete data[field.code];
				}
			}
			if (this.formModel.slaves) {
				this.formModel.slaves.forEach(slave => {
					if (this.moduleState && this.moduleState[slave.code]) {
						data[slave.code] = this.moduleState[slave.code].listData;
					}
					if (this.$refs[slave.code] && this.$refs[slave.code][0] && this.$refs[slave.code][0].getData) {
						data[slave.code] = this.$refs[slave.code][0].getData();
					}

					//清除子表非提交数据
					var deleteField = {};
					for (let i in slave.fields) {
						var field = slave.fields[i];
						if (field.status === 0) {
							deleteField[field.code] = true;
						}
					}
					for (let i in data[slave.code]) {
						for (let code in deleteField) {
							if (data[slave.code][i][code] !== undefined) {
								delete data[slave.code][i][code];
							}
						}
					}
				});
			}
			return data;
		},
		fieldsetCollaspe(fieldset) {
			fieldset.collapse = !fieldset.collapse;
		},
		updateSlave(code, value) {
			this.updateField({
				code,
				value,
			});
		},
		slaveComponent(slave) {
			if (slave.enable_attachment) {
				return 'attachmentList';
			} else if (slave.type === 'editor') {
				return 'tableEditor';
			} else if (this.isXList && 0) {
				return 'x_tableList';
			} else {
				return 'tableList';
			}
		},
		fieldControl(field) {
			if (this.view && field.tpl) {
				return 'div';
			} else {
				return this.fieldType(field);
			}
		},
		dataChange({ code, value, attach }) {},
		//强制触发验证
		doValidate() {
			this.formValidte = true;
			this.$forceUpdate();
			//自动对焦未验证的字段
			this.$nextTick(() => {
				for (let i in this.formFields) {
					var code = 'field_' + this.formFields[i].code;
					if (this.$refs[code] && this.$refs[code][0] && !this.$refs[code][0].validate) {
						this.$refs[code][0].focus();
						break;
					}
				}
			});
		},
		fieldInput(field, value) {
			this.val({
				code: field.code,
				value,
			});
			this.$nextTick(() => {
				this.formValidte = false;
				this.$emit('formInput', {
					code: field.code,
					value,
				});
			});
			//正常event触发
			this.eventTrigger(field);
			//本地evet触发 属于临时设置
			this.localEventTrigger(field, value);
		},
		//触发所有event，用于初始化
		eventUpdate() {
			for (let i in this.formModel.fields) {
				this.eventTrigger(this.formModel.fields[i]);
			}
			if (this.formModel.fields && !this.formModel.fields.length) {
				for (let i in this.fieldStatus) {
					this.eventTrigger({
						code: i,
					});
				}
			}
		},
		eventTrigger(field) {
			var code = field.code;
			if (this.fieldStatus[code] && this.fieldStatus[code].events && this.fieldStatus[code].events.length) {
				var param = {};
				if (this.formModel.main) {
					param = this.formData;
				} else {
					param = {
						...this.parentData,
						[this.formModel.code]: this.formData,
					};
				}
				this.fieldStatus[code].events.forEach(event => {
					if (event.trigger) return;
					event.trigger = true;
					var exp = $.composeValue(event.condition, param, false, true);
					var value = Formula(exp);
					if (value) {
						this.changeStatus(event);
						if (event.status) {
							for (let i in event.status) {
								switch (event.status[i]) {
									case 'hide':
										this.fieldStatus[i].show = false;
										break;
									case 'show':
										this.fieldStatus[i].show = true;
										break;
									case 'enable':
										this.fieldStatus[i].enable = true;
										break;
									case 'disbale':
										this.fieldStatus[i].enable = false;
										break;
								}
							}
						}
					} else {
						this.changeStatus(event, false);
						if (event.status) {
							for (let i in event.status) {
								switch (event.status[i]) {
									case 'hide':
										this.fieldStatus[i].show = true;
										break;
									case 'show':
										this.fieldStatus[i].show = false;
										break;
									case 'enable':
										this.fieldStatus[i].enable = false;
										break;
									case 'disbale':
										this.fieldStatus[i].enable = true;
										break;
								}
							}
						}
					}
					this.$nextTick(() => {
						event.trigger = false;
					});
				});
			}
		},
		localEventTrigger(field, value) {
			if (field.change) {
				field.change.forEach(e => {
					if (e.eqal !== undefined) {
						if (e.eqal === value || e.eqal.toString() === value) {
							for (let i in e.state) {
								switch (e.state[i]) {
									case 'hide':
										this.fieldStatus[i].show = false;
										break;
									case 'show':
										this.fieldStatus[i].show = true;
										break;
								}
							}
						} else {
							for (let i in e.state) {
								switch (e.state[i]) {
									case 'hide':
										this.fieldStatus[i].show = true;
										break;
									case 'show':
										this.fieldStatus[i].show = false;
										break;
								}
							}
						}
					}
				});
			}
		},
		fieldValidate(field, value) {
			if (!field || !field.code) {
				return;
			}
			if (this.fieldStatus[field.code] && this.fieldStatus[field.code].show === false) {
				value = true;
			}
			if (!value) {
				this.isValidate = false;
				this.validateSet.add(field.code);
			} else {
				this.validateSet.delete(field.code);
				if (!this.validateSet.size) {
					this.isValidate = true;
				}
			}
			this.$emit('validate', this.isValidate);
		},
		changeStatus(e, v = true) {
			if (e.visiables) {
				for (let code of e.visiables) {
					this.fieldStatus[code] && this.$set(this.fieldStatus[code], 'show', v);
					$.set(this.slaveShow, code, v);
					//由于不显示的元素不会进行数据更新（待确认） 需要手动将隐藏元素的验证状态置为true，防止隐藏必填项导致表单验证失败
					if (v) this.fieldValidate(this.fieldStatus[code], true);
				}
			}
			if (e.hiddens) {
				for (let code of e.hiddens) {
					this.fieldStatus[code] && this.$set(this.fieldStatus[code], 'show', !v);
					$.set(this.slaveShow, code, !v);
					if (!v) this.fieldValidate(this.fieldStatus[code], true);
				}
			}
			if (e.editables) {
				for (let code of e.editables) {
					this.fieldStatus[code] && this.$set(this.fieldStatus[code], 'enable', v);
				}
			}
			if (e.disables) {
				for (let code of e.disables) {
					this.fieldStatus[code] && this.$set(this.fieldStatus[code], 'enable', !v);
				}
			}
			this.$forceUpdate();
		},
		extFieldInput({ code, value }) {
			this.val({
				code,
				value,
			});
			this.$emit('formInput', {
				code,
				value,
			});
		},
		fieldControlCol(field) {
			var col = 24 - this.fieldLabelCol(field);
			return col;
		},
		fieldLabelCol(field) {
			var col = this.labelCol;
			if (FieldsType[field.type] && FieldsType[field.type].fullRow && this.hasFullRow) {
				col = Math.floor(col / this.formCol);
			}
			return col;
		},
		fieldType(field) {
			return Fields.fieldType(field);
		},
		fieldGroupCol(field) {
			var col = Math.floor(24 / this.formCol);
			if (FieldsType[field.type] && FieldsType[field.type].fullRow && this.hasFullRow) {
				col = col * this.formCol;
			}
			/*
      if (this.hasTextTip) {
        col = col * this.formCol;
      }
      */
			return col;
		},
		groupClass(field) {
			return {
				['ivu-col-span-' + this.fieldGroupCol(field)]: true,
			};
		},
		slaveGroupClass(field) {
			return {
				['ivu-col-span-' + this.slaveGroupCol(field)]: true,
			};
		},
		slaveGroupCol(field) {
			var col = Math.floor(24 / this.formCol);
			col = col * this.formCol;
			return col;
		},
		slaveControlCol(field) {
			var col = 24 - this.slaveLabelCol(field);
			return col;
		},
		slaveLabelCol(field) {
			var col = this.labelCol;
			col = Math.floor(col / this.formCol);
			return col;
		},
		tipText(field) {
			if (!field.tip || field.tip === '提示信息') return '';
			var param = {
				...this.formData,
			};
      if (this.$parentAction) {
				param.parent = this.$parentAction.actionData;
			}
      this.tipContent = param;
			return $.composeValue(field.tip, param);
		}
	},
	mounted() {
		this.$emit('build');
		if (this.hasSlaves && this.formModel.slaves) {
			this.formModel.slaves.forEach(slave => {
				if (this.$refs[slave.code]) {
					let table = this.$refs[slave.code][0];
					table.$mainForm = this;
				}
				if (this.moduleState && this.moduleState[slave.code]) {
					this.val({
						code: slave.code,
						name: this.moduleState[slave.code].listData,
					});
				}
			});
		}
		this.$nextTick(() => {
			if (this.$parentAction && this.$parentAction.$owner.$mainForm) {
				this.$set(this, 'parentData', this.$parentAction.$owner.$mainForm.formData);
			} else if (this.$parentAction) {
				this.$set(this, 'parentData', this.$parentAction.actionData);
			}
		});
	},
	created() {
		this.setData(this.value);
		if (this.initData) {
			this.initDefaultData();
		}
		this.setModel($.copy(this.model));
		this.moduleState.formModel.fields.forEach(field => {
			this.fieldStatus[field.code] = {
				code: field.code,
				show: true,
				enable: null,
				events: [],
			};
		});
		if (this.moduleState.formModel.events) {
			this.moduleState.formModel.events.forEach(event => {
				let param = $.valueParam(event.condition);
				for (let i in param) {
					let code = i;
					if (!this.formModel.main) {
						if (code.indexOf(this.moduleState.formModel.code + '.') === 0) {
							code = code.replace(this.moduleState.formModel.code + '.', '');
						} else {
							continue;
						}
					}
					if (this.fieldStatus[code]) {
						this.fieldStatus[code].events.push(event);
					} else {
						this.fieldStatus[code] = {
							code: code,
							show: false,
							enable: null,
							events: [event],
						};
					}
				}
			});
		}

		var list = {
			top: {
				code: 'top',
				fields: [],
				index: 0,
				collapse: false,
			},
			default: {
				code: 'default',
				fields: [],
				index: 99,
				collapse: false,
			},
			bottom: {
				code: 'bottom',
				fields: [],
				index: 999,
				collapse: false,
			},
		};
		if (this.formModel.fieldset) {
			this.formModel.fieldset.forEach((item, index) => {
				if (list[item.code]) {
					list[item.code] = $.setObj(item, list[item.code]);
				} else {
					list[item.code] = {
						collapse: false,
						...item,
						fields: [],
						index: index + 1,
					};
				}
			});
		}
		this.fieldsetList = list;

		if (this.impData) {
			this.setData(this.impData);
		}
	},
	beforeCreate() {
		//this.$options.components.x_tableList = require('components/x_localGridPanel/index.vue');
	},
	components: {
		tableList,
		tableEditor,
		attachmentList,
		TabsPro,
		...Fields.control,
	},
};
</script>

<style lang="less">
.fieldset-wrapper {
	hr {
		clear: both;
		margin: 0px 0px 16px;
	}
	.fieldset-header {
		position: relative;
		border-left: 4px solid #168cf3;
		font-size: 12px;
		padding: 4px 12px;
		margin-bottom: 8px;
		cursor: pointer;
		&:hover {
			border-color: #57a3f3;
		}
		.collapse-box {
			position: absolute;
			right: 4px;
			top: 4px;
			float: right;
			font-size: 14px;
		}
	}
	.field-control.field-text {
		line-height: 34px;
		color: #5b5b5b;
		background: #f7f7f7;
		border: none;
		cursor: auto;
		padding: 0 7px;
	}
	.field-has-tip {
		.field-control {
			width: 60%;
			float: left;
		}
		.field-tip {
			width: 40%;
			float: left;
			line-height: 31px;
			padding: 0 16px;
		}
	}
	.fieldset-body {
		position: relative;
		transition: height 0.35s ease;
		&.fieldset-body-collapse {
			height: 0;
			overflow: hidden;
		}
	}
}

.field-group-tabs {
	margin: 16px;
	.ivu-tabs {
		/*padding-top: 32px;*/
	}
	.ivu-tabs-nav .ivu-tabs-tab {
		font-size: 13px;
	}
}

.field-group.slave-group {
	padding-top: 24px;
}
</style>
